/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import org.springframework.lang.Nullable;

/**
 * 由定义request和handler对象之间映射的对象实现的接口.
 *
 * <p>这个类可以由应用程序开发人员实现, 尽管这不是必要的, 因为框架中包含了
 * {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping}
 * 和{@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping}.
 * 如果在application context中没有注册HandlerMapping bean, 则前者是默认的.
 *
 * <p>HandlerMapping实现可以支持映射的interceptor, 但不必这样做. handler将始终包装在
 * {@link HandlerExecutionChain}实例中, 并可选择附带一些{@link HandlerInterceptor}
 * 实例. DispatcherServlet将首先按照给定的顺序调用每个HandlerInterceptor的{@code preHandle}
 * 方法, 最后在所有{@code preHandle}方法都返回{@code true}的情况下调用handler本身.
 *
 * <p>参数化这个映射的能力是这个MVC框架的一个强大而不同寻常的功能. 例如, 可以根据session状态、
 * cookie状态或许多其他变量编写自定义映射. 似乎没有其他MVC框架具有同样的灵活性.
 *
 * <p>注意: 实现可以显示{@link org.springframework.core.Ordered}接口, 以便呢能够指定排序顺序,
 * 从而指定DispatcherServlet应用的优先级. 未排序的实例将被视为优先级最低的实例.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @see org.springframework.core.Ordered
 * @see org.springframework.web.servlet.handler.AbstractHandlerMapping
 * @see org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
 * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
 */
public interface HandlerMapping {

	/**
	 * {@link HttpServletRequest}属性的名称, 该属性包含最佳匹配模式的映射handler.
	 * @since 4.3.21
	 */
	String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";

	/**
	 * {@link HttpServletRequest}属性的名称, 该属性包含用于查找matcher handler的路径,
	 * 根据配置的{@link org.springframework.web.util.UrlPathHelper}, matcher handler
	 * 可以是完整路径, 也可以没有context path, 是否decoded等等.
	 * @since 5.2
	 * @deprecated as of 5.3 in favor of
	 * {@link org.springframework.web.util.UrlPathHelper#PATH_ATTRIBUTE} and
	 * {@link org.springframework.web.util.ServletRequestPathUtils#PATH_ATTRIBUTE}.
	 * To access the cached path used for request mapping, use
	 * {@link org.springframework.web.util.ServletRequestPathUtils#getCachedPathValue(ServletRequest)}.
	 */
	@Deprecated
	String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath";

	/**
	 * {@link HttpServletRequest}属性的名称, 在模式匹配的情况下, 该属性包含handler映射中的路径,
	 * 或者完整的相关URI(通常在DispatcherServlet的映射中).
	 * <p>注意: 并非所有HandlerMapping实现都需要支持此属性. 基于URL的HandlerMappings通常会支持
	 * 它, 但handler不一定期望此request属性出现在所有场景中.
	 */
	String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";

	/**
	 * {@link HttpServletRequest}属性的名称, 该属性包含handler映射中的最佳匹配模式.
	 * <p>注意: 并非所有HandlerMapping实现都需要支持此属性. 基于URL的HandlerMappings
	 * 通常会支持它, 但handler不一定期望此request属性出现在所有场景中.
	 */
	String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";

	/**
	 * 指示是否应检查类型级映射的boolean{@link HttpServletRequest}属性的名称.
	 * <p>注意: 并非所有的HandlerMapping实现都需要支持此属性.
	 */
	String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";

	/**
	 * 包含URI模板映射的{@link HttpServletRequest}属性的名称, 将变量名映射到值.
	 * <p>注意: 并非所有的HandlerMappings实现都需要支持此属性. 基于URL的HandlerMappings
	 * 通常会支持它, 但handler不一定期望此request属性出现在所有场景中.
	 */
	String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";

	/**
	 * {@link HttpServletRequest}属性的名称, 该属性包含一个带有URI变量名称的映射,
	 * 以及每个URI矩阵变量的相应MultiValueMap.
	 * <p>注意: 并非所有HandlerMapping实现都需要支持此属性, 也可能不存在此属性, 具体
	 * 取决于HandlerMapping是否配置为保留矩阵变量内容.
	 */
	String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";

	/**
	 * {@link HttpServletRequest}属性的名称, 该属性包含适用于映射handler的一组
	 * producible MediaTypes.
	 * <p>注意: 并非所有HandlerMapping实现都需要支持此属性. handler不一定期望这个request属性出现在所有场景中.
	 */
	String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";


	/**
	 * 此{@code HandlerMapping}实例是否已启用以使用解析的
	 * {@link org.springframework.web.util.pattern.PathPattern}s, 在这种情况下,
	 * {@link DispatcherServlet}会自动
	 * {@link org.springframework.web.util.ServletRequestPathUtils#parseAndCache parses}
	 * {@code RequestPath}, 使其可用于{@code HandlerMapping}s, {@code HandlerInterceptor}和
	 * 其他组件中的{@link org.springframework.web.util.ServletRequestPathUtils#getParsedRequestPath
	 * access}.
	 * @since 5.3
	 */
	default boolean usesPathPatterns() {
		return false;
	}

	/**
	 * 返回此request的handler和任何interceptor. 可以根据请求URL、session状态或实现类选择的
	 * 任何因素进行选择.
	 * <p>返回的HandlerExecutionChain包含一个handler对象, 而不是一个标记接口, 因此handler
	 * 不会受到任何约束. 例如, 可以编写HandlerAdapter以允许使用另一个框架的handler对象.
	 * <p>如果未找到匹配项, 则返回{@code null}. 这不是一个错误. DispatcherServlet将查询
	 * 所有注册的HandlerMapping bean以找到匹配项, 并且只有在没有人能找到handler的情况下才确定
	 * 存在错误.
	 * @param request 当前HTTP请求
	 * @return 包含handler和任何interceptor的HandlerExecutionChain实例,
	 * 如果未找到映射, 则为{@code null}
	 * @throws Exception 如果存在内部错误
	 */
	@Nullable
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

}
